import * as THREE from "../../../modules/three/three.module.js";
import {getYAngleDeg, toFixedVector} from "../lib/util/StaticMethods.js";

const droneHeading = new THREE.Vector3()
const droneOffset = new THREE.Vector3()
const dronePosition = new THREE.Vector3()

export const RoutePointActions = {
  StartSpray: 'startSpraying',
  EndSpray: 'endSpraying',
  Hovering: 'hoverTime', // 'hoverTime 5' 表示需要悬停5秒，'hoverTime 10' 表示需要悬停10秒
}

export const OffsetEnum = {
  h: 'h',
  up: 'u',
  down: 'd',
}
// 喷涂航线的航点
export default class RoutePointVO {
  position = new THREE.Vector3()
  normal = new THREE.Vector3(0, 1, 0)
  // 沿 normal 偏移的距离，水平面上的偏移距离，单位米
  offset = 2
  // 无人机距离喷涂点的高程差值，铅锤线上的偏移距离，单位米
  above = 1.5
  // 无人机相对于喷涂点的偏移类型：水平偏移，竖直偏移  默认为水平
  offsetType = OffsetEnum.h
  action = ''
  // 航点半径
  radius = 0.5
  // _heading = new THREE.Vector3()
  // _dronePos = new THREE.Vector3()

  constructor() {
  }

  cloneRoutePoint() {
    const copy = new RoutePointVO()
    copy.position.copy(this.position)
    copy.normal.copy(this.normal)
    copy.offset = this.offset
    copy.above = this.above
    copy.action = this.action
    copy.offsetType = this.offsetType
    copy.radius = this.radius
    return copy
  }

  copy(other) {
    this.position.copy(other.position)
    this.normal.copy(other.normal)
  }
  /**
   * 设置航点动作
   * @param {string} action
   * @see {RoutePointActions}
   */
  setAction(action) {
    this.action = action
  }
  /**
   * @see {DroneFlyPath.fromAI}
   * @return {number}
   */
  startSpraying() {
    return this.action.includes(RoutePointActions.StartSpray) ? 1 : 0
  }
  endSpraying() {
    return this.action.includes(RoutePointActions.EndSpray) ? 1 : 0
  }
  hoverTime() {
    if (!this.action.includes(RoutePointActions.Hovering)) {
      return 0
    }
    const arr0 = this.action.split(',')
    const str = arr0.find(it => it.includes(RoutePointActions.Hovering)).trim()
    const arr = str.split(' ')
    return parseInt(arr[1])
  }

  updateOffsetSize(val) {
    if (this.offsetType === 'h') {
      this.offset = val
    } else {
      this.above =val
    }
  }
  getOffsetSize() {
    return this.offsetType === 'h' ? this.offset : this.above
  }

  getDronePosAndHeading() {
    if (this.offsetType === OffsetEnum.h) {
      droneOffset.copy(this.normal)
      droneOffset.z = 0
      droneOffset.normalize()
    } else {
      if (this.offsetType === OffsetEnum.down) {
        droneOffset.set(0,0, -1)
      } else {
        droneOffset.set(0, 0, 1)
      }
    }
    droneHeading.copy(droneOffset).negate()
    droneOffset.multiplyScalar(this.getOffsetSize())
    dronePosition.copy(this.position).add(droneOffset)
    let yaw = getYAngleDeg(droneHeading.x, droneHeading.y)
    while (yaw > 180 || yaw < -180) {
      if (yaw > 180) {
        yaw -= 360
      } else if (yaw < -180) {
        yaw += 360
      }
    }
    // this._heading.copy(droneHeading)
    // this._dronePos.copy(dronePosition)
    // return {dronePosition: this._dronePos, droneHeading: this._heading}
    return {dronePosition, droneHeading, yaw}
  }

  toJsonObj() {
    const obj = {offset: this.offset, above: this.above, action: this.action, offsetType: this.offsetType}
    obj.dir = this.normal.toArray()
    obj.pos = toFixedVector(this.position, 3).toArray()
    obj.radius = this.radius
    return obj
  }

  fromJsonObj(jsonObj) {
    this.position.fromArray(jsonObj.pos);
    this.normal.fromArray(jsonObj.dir);
    this.offset = jsonObj.offset;
    this.above = jsonObj.above || 1.5;
    this.offsetType = jsonObj.offsetType || 'h';
    this.action = jsonObj.action
    this.radius = jsonObj.radius || 0.5
    return this;
  }
}
